﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace Iworld.ViewModel
{
    /// <summary>
    /// 视图模型服务基类
    /// </summary>
    /// <typeparam name="TPage">页面标识枚举</typeparam>
    /// <typeparam name="TPop">弹窗标识枚举</typeparam>
    public abstract class ViewModelServiceBase<TPage,TPop> 
        where TPage : struct
        where TPop : struct
    {
        private Dictionary<PageCreaterKey, UIElementCreater> _pageCreaters = new Dictionary<PageCreaterKey, UIElementCreater>();

        private Dictionary<TPop, PopCreater> _popCreaters = new Dictionary<TPop, PopCreater>();

        private IMainPage<TPage, TPop> root;

        TPage? current = null;

        public ViewModelServiceBase(IMainPage<TPage,TPop> root)
        {
            this.root = root;
            this.root.RegisterViews(this);
        }

        //DataContext所在的程序集
        protected abstract Assembly GetViewModelAssembly();

        protected abstract string GetViewModelName(string pageTypeName);

        /// <summary>
        /// 跳转之前调用,返回false则停止跳转
        /// </summary>
        /// <param name="key"></param>
        protected virtual bool OnJumping(PageCreaterKey key) { return true; }

        /// <summary>
        /// 跳转之后调用
        /// </summary>
        /// <param name="key"></param>
        protected virtual void OnJumped(PageCreaterKey key) { }
        
        /// <summary>
        /// 当前的界面
        /// </summary>
        public TPage? CurrentPage
        {
            get { return current; }
        }

        public void JumpToDefaultPage()
        {
            bool haveCreater = _pageCreaters.Any(x => x.Key.IsDefault);
            if (!haveCreater)
            {
                throw new Exception("指定的界面并没有在系统中注册");
            }
            TPage page = _pageCreaters.Where(x => x.Key.IsDefault).Select(x => x.Key.Page).Single();
            JumpTo(page);
        }

        public virtual void JumpTo(string pageName)
        {
            try
            {
                TPage page = (TPage)Enum.Parse(typeof(TPage), pageName, false);
                JumpTo(page);
            }
            catch (Exception)
            {
                JumpToDefaultPage();
            }
            
        }
 
        public void JumpTo(TPage page, params object[] args)
        {
            bool haveCreater = _pageCreaters.Any(x => x.Key.Page.Equals(page));
            if (!haveCreater)
            {
                throw new Exception("指定的界面并没有在系统中注册");
            }
            PageCreaterKey key = _pageCreaters.Where(x => x.Key.Page.Equals(page)).Select(x => x.Key).Single();
            if (!OnJumping(key))
                return;
            UIElementCreater creater = _pageCreaters[key];
            UIElement element = creater();
            root.DataContext = GetViewModel(key, args);
            root.Show(element);
            current = page;
            OnJumped(key);
        }

        protected virtual object GetViewModel(PageCreaterKey key, params object[] args)
        {
            return CreateInstance(GetViewModelAssembly(),key.ViewModelName,args);
        }

        protected object CreateInstance(Assembly assembly,string typeName,params object[] args)
        {
            if (args != null)
            {
                var t = assembly.GetType(typeName, true);
                return Activator.CreateInstance(t, args);
            }
            else
            {
                return assembly.CreateInstance(typeName);
            }
        }


        public void RegisterPage(TPage view, string pageName, bool isDefault, UIElementCreater creater)
        {
            bool haveCreater = _pageCreaters.Any(x => x.Key.Page.Equals(view));
            if (haveCreater)
            {
                throw new Exception("该界面已经被注册到界面池，请检查程序");
            }
            if (isDefault)
            {
                bool hadDefault = _pageCreaters.Any(x => x.Key.IsDefault);
                if (hadDefault)
                {
                    throw new Exception("已经有一个被声明为默认界面的界面被注册到界面池，请检查程序");
                }
            }
            PageCreaterKey key = new PageCreaterKey()
            { 
                IsDefault=isDefault,
                Page=view,
                PageTypeName=pageName, 
                ViewModelName= this.GetViewModelName(pageName)
            };
            _pageCreaters.Add(key, creater);
        }

        public void RegisterPop(TPop pop, PopCreater creater)
        {
            #region 检查弹窗池

            bool hadPop = _popCreaters.Any(x => x.Key.Equals(pop));
            if (hadPop)
            {
                throw new Exception("该弹窗已经被注册到弹窗池，请检查程序");
            }

            #endregion
            _popCreaters.Add(pop, creater);
        }

        /// <summary>
        /// 获取弹窗对象
        /// </summary>
        /// <param name="pop">弹窗标识</param>
        /// <returns>返回弹窗对象</returns>
        public IPop GetPop(TPop pop)
        {
            bool hadPop = _popCreaters.Any(x => x.Key.Equals(pop));
            if (!hadPop)
            {
                throw new Exception("该弹窗没有被注册");
            }

            PopCreater creater = _popCreaters.Where(x => x.Key.Equals(pop)).Select(x => x.Value).Single();
            return creater();
        }


        protected class PageCreaterKey
        {
            /// <summary>
            /// 界面标识
            /// </summary>
            public TPage Page { get; set; }

            /// <summary>
            /// 视图模型的名称
            /// </summary>
            public string ViewModelName { get; set; }

            /// <summary>
            /// 页面类型名称
            /// </summary>
            public string PageTypeName { set; get; }

            /// <summary>
            /// 一个布尔值 表示被标记对象是否为默认界面
            /// </summary>
            public bool IsDefault { get; set; }

        }
     }


    /// <summary>
    /// UI元素的创建者委托
    /// </summary>
    /// <returns>返回界面实例</returns>
    public delegate UIElement UIElementCreater();

    public delegate IPop PopCreater();

}

  
 


